<template>
  <view class="chat-detail-container">
    <!-- 顶部导航栏 -->
    <view class="chat-header">
      <view class="back-btn" @click="goBack">
        <FeatherIcon name="chevron-left" size="24" color="#333" />
      </view>
      <view class="header-right-space"></view>
      <view class="user-info">
        <text
          class="username"
          @click="navigateToUserDetail(chatTarget?.userName || '')"
        >
          {{
            chatTarget?.userNickname
              ? chatTarget?.userNickname + "(" + chatTarget?.userName + ")"
              : chatTarget?.userName || "加载中..."
          }}
        </text>
        <text class="status" v-if="chatTarget?.userOnlineFlag">在线</text>
        <text class="status-offline" v-else>离线</text>
      </view>
    </view>

    <!-- 聊天内容区域 -->
    <scroll-view
      class="chat-messages"
      scroll-y
      :scroll-top="scrollTop"
      @scrolltoupper="loadMoreMessages"
      :scroll-with-animation="false"
      :show-scrollbar="false"
      :style="{ height: contentHeight + 'px' }"
      id="chat-scroll"
      ref="scrollView"
      :scroll-anchoring="true"
      :enhanced="true"
      :bounces="false"
    >
      <view class="chat-list">
        <view class="loading-more" v-if="loading">
          <text>加载中...</text>
        </view>

        <!-- 没有更多消息提示 -->
        <view
          class="no-more"
          v-if="!hasMore && messages && messages.length > 0"
        >
          <text>没有更多消息了</text>
        </view>

        <!-- 消息列表 -->
        <block v-for="(message, index) in messages" :key="message.oId">
          <!-- 日期分割线，当日期变化或者是第一条消息时显示 -->
          <view
            class="date-divider"
            v-if="
              index === 0 ||
              isDifferentDay(messages[index - 1].time, message.time)
            "
          >
            <text>{{ formatDateHeader(message.time) }}</text>
          </view>

          <!-- 消息项 -->
          <view class="message-group">
            <!-- 时间显示 - 如果与上一条消息间隔超过5分钟则显示时间 -->
            <view class="time-indicator" v-if="shouldShowTime(index, message)">
              <text>{{ formatMessageTime(message.time) }}</text>
            </view>

            <!-- 他人的消息 -->
            <view class="message-wrapper" v-if="!isSelfSender(message)">
              <view
                class="avatar-container"
                @click="navigateToUserDetail(message.senderUserName)"
              >
                <image
                  class="avatar"
                  :src="message.senderAvatar"
                  mode="aspectFill"
                ></image>
              </view>
              <view class="message-content">
                <view
                  class="message-bubble other-bubble"
                  @tap.capture="handleMessageTap($event, message)"
                >
                  <rich-text
                    :nodes="formatContent(message.content)"
                  ></rich-text>
                </view>
              </view>
            </view>

            <!-- 自己的消息 -->
            <view class="message-wrapper self-wrapper" v-else>
              <view class="avatar-container">
                <image
                  class="avatar"
                  :src="message.senderAvatar"
                  mode="aspectFill"
                ></image>
              </view>
              <view class="message-content self-content">
                <view
                  class="message-bubble self-bubble"
                  @tap.capture="handleMessageTap($event, message)"
                >
                  <rich-text
                    :nodes="formatContent(message.content)"
                  ></rich-text>
                </view>
              </view>
            </view>
          </view>
        </block>

        <view
          class="empty-state"
          v-if="messages && messages.length === 0 && !loading"
        >
          <text class="empty-text">暂无聊天记录，开始对话吧</text>
        </view>
      </view>
    </scroll-view>

    <!-- 底部输入区域 -->
    <view
      class="input-area"
      v-if="isLoggedIn"
      :style="{ bottom: keyboardHeight + 'px' }"
    >
      <view class="input-wrapper">
        <view class="emoji-btn" @click="handleEmoji">
          <FeatherIcon name="smile" size="24" color="#666" />
        </view>
        <input
          class="message-input"
          type="text"
          v-model="messageContent"
          placeholder="说点什么..."
          confirm-type="send"
          @confirm="handleInputConfirm"
          @focus="handleInputFocus"
          @blur="handleInputBlur"
          :adjust-position="false"
        />
        <!-- 根据输入内容显示不同按钮 -->
        <view
          v-if="messageContent.trim()"
          class="send-btn"
          @click="sendMessage"
        >
          <FeatherIcon name="send" size="24" color="#fff" />
        </view>
        <view v-else class="more-btn" @click="toggleMorePanel">
          <FeatherIcon name="plus" size="24" color="#666" />
        </view>
      </view>

      <!-- 表情面板 -->
      <view class="emoji-panel" v-if="showEmojiPanel">
        <view class="emoji-tabs">
          <view
            class="emoji-tab"
            :class="{ 'active-tab': activeEmojiTab === 'default' }"
            @click="switchToDefaultTab"
          >
            <text>默认表情</text>
          </view>
          <view
            class="emoji-tab"
            :class="{ 'active-tab': activeEmojiTab === 'custom' }"
            @click="switchToCustomTab"
          >
            <text>我的表情</text>
          </view>
        </view>

        <swiper
          class="emoji-swiper"
          :current="activeEmojiTab === 'default' ? 0 : 1"
          @change="handleEmojiTabChange"
        >
          <!-- 默认表情 -->
          <swiper-item>
            <scroll-view
              scroll-y
              class="emoji-scroll"
              v-if="defaultEmoticons.length > 0"
            >
              <view class="emoji-list">
                <view
                  class="emoji-item"
                  v-for="(emoji, index) in defaultEmoticons"
                  :key="'default-' + index"
                  @click="selectEmoji(emoji)"
                >
                  <text class="emoji-text" v-if="!isImageUrl(emoji)">{{
                    emoji
                  }}</text>
                  <image
                    v-else
                    class="emoji-image"
                    :src="emoji"
                    mode="aspectFit"
                  ></image>
                </view>
              </view>

              <!-- 空状态 -->
              <view
                class="emoji-empty"
                v-if="defaultEmoticons.length === 0 && !isLoadingEmoticons"
              >
                <text>暂无默认表情</text>
              </view>
            </scroll-view>
          </swiper-item>

          <!-- 用户表情包 -->
          <swiper-item>
            <scroll-view scroll-y class="emoji-scroll">
              <view class="emoji-list">
                <!-- 添加表情按钮放在开头 -->
                <view class="emoji-item add-emoji-item" @click="addCustomEmoji">
                  <view class="add-emoji-icon">
                    <FeatherIcon name="plus-square" size="40" color="#666" />
                  </view>
                </view>

                <view
                  class="emoji-item"
                  v-for="(emoji, index) in customEmoticons"
                  :key="'custom-' + index"
                  @click="selectEmoji(emoji)"
                  @longpress="handleLongPress(index)"
                >
                  <image
                    class="emoji-image"
                    :src="emoji"
                    mode="aspectFit"
                    :class="{
                      'emoji-delete-active': selectedEmojiIndex === index,
                    }"
                  ></image>
                  <view
                    class="emoji-delete-icon"
                    v-if="selectedEmojiIndex === index"
                    @click.stop="deleteEmoji(index)"
                  >
                    <FeatherIcon name="trash-2" size="24" color="#ff4d4f" />
                  </view>
                </view>
              </view>

              <!-- 空状态 -->
              <view
                class="emoji-empty custom-empty"
                v-if="customEmoticons.length === 0 && !isLoadingCustomEmoticons"
              >
                <text>暂无自定义表情</text>
                <button class="add-emoji-btn" @click="addCustomEmoji">
                  添加表情包
                </button>
              </view>
            </scroll-view>
          </swiper-item>
        </swiper>

        <!-- 加载中 -->
        <view
          class="emoji-loading"
          v-if="isLoadingEmoticons || isLoadingCustomEmoticons"
        >
          <text>加载表情中...</text>
        </view>
      </view>

      <!-- 功能面板 -->
      <view class="more-panel" v-if="showMorePanel">
        <view class="more-list">
          <view class="more-item" @click="handleTransfer">
            <FeatherIcon name="dollar-sign" size="24" color="#666" />
            <text>转账</text>
          </view>
          <view class="more-item" @click="handleUploadImage">
            <FeatherIcon name="image" size="24" color="#666" />
            <text>图片</text>
          </view>
        </view>
      </view>
    </view>

    <!-- 未登录提示 -->
    <view class="login-prompt" v-else @click="goToLogin">
      <view class="login-content">
        <FeatherIcon name="lock" size="24" color="#007AFF" />
        <text>登录后参与聊天</text>
      </view>
    </view>

    <!-- 单张图片预览模态框 -->
    <view class="image-preview-modal" v-if="showImagePreview">
      <view class="image-preview-mask" @tap.stop="closeImagePreview"></view>
      <ImageViewer
        :value="[{ url: previewImageUrl }]"
        :editable="false"
        :itemSize="0"
        @preview-close="closeImagePreview"
      />
    </view>

    <!-- 自定义转账弹框 -->
    <view class="transfer-modal" v-if="showTransferModal">
      <view class="modal-mask" @click="closeTransferModal"></view>
      <view class="modal-content" :style="{ bottom: keyboardHeight + 'px' }">
        <view class="modal-header">
          <text class="modal-title"
            >转账给 {{ chatTarget.userNickname || chatTarget.userName }}</text
          >
          <view class="modal-close" @click="closeTransferModal">
            <FeatherIcon name="x" size="20" color="#666" />
          </view>
        </view>
        <view class="modal-body">
          <view class="input-group">
            <text class="input-label">转账金额</text>
            <view class="input-wrapper">
              <text class="currency-symbol">¥</text>
              <input
                class="input-field"
                type="digit"
                v-model="transferAmount"
                placeholder="0.00"
                focus
                :adjust-position="false"
              />
            </view>
          </view>
          <view class="input-group">
            <text class="input-label">备注（选填）</text>
            <input
              class="input-field"
              type="text"
              v-model="transferMemo"
              placeholder="请输入转账备注"
              :adjust-position="false"
            />
          </view>
          <view class="balance-info">
            <text>当前余额：{{ currentUser?.userPoint || 0 }} 积分</text>
          </view>
        </view>
        <view class="modal-footer">
          <button class="modal-btn cancel-btn" @click="closeTransferModal">
            取消
          </button>
          <button
            class="modal-btn confirm-btn"
            @click="confirmTransfer"
            :disabled="!transferAmount"
          >
            确认转账
          </button>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup>
import {
  ref,
  reactive,
  onMounted,
  nextTick,
  computed,
  onUnmounted,
  onBeforeUnmount,
} from "vue";
import { isLoggedIn, getApiKey } from "@/api";
import api from "@/api";
import FeatherIcon from "@/components/FeatherIcon.vue";
import ImageViewer from "@/components/ImageViewer.vue";
import {
  formatDate,
  showLoading,
  hideLoading,
  showError,
  showSuccess,
} from "@/utils/common.js";
// 导入聊天室WebSocket服务，用于销毁连接
import { useChatWebSocket } from "@/services/ChatWebSocket.js";
import { chooseAndUploadImage } from "@/utils/upload";

// 页面是否可见
const isPageVisible = ref(true);
// 聊天目标用户信息
const chatTarget = ref({});
const theOtherSideUserName = ref("");
// 消息列表
const messages = ref([]);
// 消息内容
const messageContent = ref("");
// 是否在发送中
const sending = ref(false);
// 是否在加载中
const loading = ref(false);
// 是否还有更多消息
const hasMore = ref(true);
// 当前页码
const page = ref(1);
// 每页消息数量
const pageSize = ref(20);
// 滚动位置
const scrollTop = ref(0);
// 内容区域高度
const contentHeight = ref(0);
// 当前用户
const currentUser = ref(null);
// 是否显示表情面板
const showEmojiPanel = ref(false);
// 表情列表
const emoticonList = ref([]);
// 滚动视图引用
const scrollView = ref(null);
// 输入框焦点控制
const commentFocus = ref(false);

// WebSocket 连接
const socketTask = ref(null);
const isConnected = ref(false);
const reconnectTimer = ref(null);
const reconnectCount = ref(0);
const MAX_RECONNECT_COUNT = 5;
const windowResizeListener = ref(null); // 添加窗口大小变化监听器引用

// 是否显示功能面板
const showMorePanel = ref(false);

// 转账相关
const showTransferModal = ref(false);
const transferAmount = ref("");
const transferMemo = ref("私信转账");

// 表情包相关
const defaultEmoticons = ref([]); // 默认表情
const customEmoticons = ref([]); // 用户表情包
const isLoadingEmoticons = ref(false); // 是否正在加载默认表情
const isLoadingCustomEmoticons = ref(false); // 是否正在加载自定义表情
const keyboardHeight = ref(0); // 键盘高度
const activeEmojiTab = ref("default"); // 当前激活的表情tab
const hasLoadedCustomEmoticons = ref(false); // 是否已加载过自定义表情
const selectedEmojiIndex = ref(-1); // 选中要删除的表情索引

// 路由参数处理
const getRouteParams = () => {
  const pages = getCurrentPages();
  const currentPage = pages[pages.length - 1];
  const { username } = currentPage.$page.options;

  if (username) {
    theOtherSideUserName.value = username;
  } else {
    showError("参数错误");
    goBack();
  }
};

// 跳转到用户详情页
const navigateToUserDetail = (username) => {
  uni.navigateTo({
    url: `/pages/user/user-profile?username=${username}`,
  });
};

// 加载对方用户资料
const loadUserProfile = async () => {
  try {
    const res = await api.user.getProfile(theOtherSideUserName.value);
    if (res !== null) {
      console.log("加载对方用户资料成功", res);

      chatTarget.value = res;
    } else {
      uni.showToast({
        title: res.msg || "获取对方用户资料失败",
        icon: "none",
      });
    }
  } catch (error) {
    console.error("获取对方用户资料失败", error);
    uni.showToast({
      title: "获取对方用户资料失败，请稍后再试",
      icon: "none",
    });
  }
};

// 加载用户信息
const loadUserInfo = async () => {
  if (!isLoggedIn()) return;

  try {
    const res = await api.user.getCurrentUser();
    if (res.code === 0) {
      currentUser.value = res.data;
    }
  } catch (error) {
    console.error("获取用户信息失败:", error);
  }
};

// 加载聊天消息
const loadMessages = async (refresh = false) => {
  console.log("加载聊天消息");
  console.log(theOtherSideUserName.value);

  if (loading.value && !refresh) return;

  try {
    loading.value = true;

    if (refresh) {
      page.value = 1;
      hasMore.value = true;
    }

    const res = await api.chat.getMessageDetail(
      theOtherSideUserName.value,
      page.value,
      pageSize.value
    );
    if (res.result === 0) {
      // 处理消息数据
      const processedMessages = (res.data || []).map((msg) => {
        return {
          ...msg,
        };
      });
      if (refresh) {
        // 确保消息从旧到新排序（最新的在最下面）
        messages.value = processedMessages.reverse();
      } else {
        // 加载更多时，新消息应该加在列表前面
        messages.value = [...processedMessages.reverse(), ...messages.value];
      }
      hasMore.value = processedMessages.length >= pageSize.value;
      // 消息加载完成后滚动到底部
      if (refresh && messages.value.length > 0) {
        await nextTick();
        scrollToBottom();
      }
    } else {
      showError(res.msg || "获取聊天记录失败");
    }
  } catch (error) {
    showError(error.message || "获取聊天记录失败");
  } finally {
    loading.value = false;
  }
};

// 加载更多消息
const loadMoreMessages = () => {
  if (hasMore.value && !loading.value) {
    page.value++;
    loadMessages();
  }
};

// 建立 WebSocket 连接
const connectWebSocket = () => {
  // 如果已经存在连接，先关闭
  if (socketTask.value) {
    socketTask.value.close({
      success: () => {
        console.log("关闭旧连接成功");
      },
      fail: (err) => {
        console.error("关闭旧连接失败:", err);
      },
    });
    socketTask.value = null;
  }

  const apiKey = getApiKey();
  if (!apiKey) {
    console.log("未登录，不建立 WebSocket 连接");
    return;
  }

  const wsUrl = `wss://fishpi.cn/chat-channel?apiKey=${apiKey}&toUser=${theOtherSideUserName.value}`;

  socketTask.value = uni.connectSocket({
    url: wsUrl,
    success: () => {
      console.log("WebSocket 连接成功");
    },
    fail: (err) => {
      console.error("WebSocket 连接失败:", err);
      handleWebSocketError(err);
    },
  });

  // 监听 WebSocket 连接打开
  socketTask.value.onOpen(() => {
    console.log("WebSocket 连接已打开");
    isConnected.value = true;
    reconnectCount.value = 0; // 重置重连次数
    if (reconnectTimer.value) {
      clearTimeout(reconnectTimer.value);
      reconnectTimer.value = null;
    }
  });

  // 监听 WebSocket 接收消息
  socketTask.value.onMessage((res) => {
    console.log("收到消息:", res);
    try {
      const message = JSON.parse(res.data);
      handleReceivedMessage(message);
    } catch (error) {
      console.error("解析消息失败:", error);
    }
  });

  // 监听 WebSocket 连接关闭
  socketTask.value.onClose(() => {
    console.log("WebSocket 连接已关闭");
    isConnected.value = false;
    handleWebSocketClose();
  });

  // 监听 WebSocket 错误
  socketTask.value.onError((err) => {
    console.error("WebSocket 错误:", err);
    handleWebSocketError(err);
  });
};

// 处理接收到的消息
const handleReceivedMessage = (message) => {
  if (!message || !message.content) return;

  try {
    // 如果是自己发送的消息，不添加到列表中
    if (message.fromId === currentUser.value?.oId) {
      return;
    }

    // 尝试解析 content 中的 JSON
    let content = message.content;

    // 检查内容是否已经是HTML (包含img标签或p标签)
    const isHTML =
      typeof content === "string" &&
      (content.includes("<img") || content.includes("<p>"));

    if (!isHTML) {
      try {
        if (typeof content === "string" && content.trim()) {
          // 移除HTML标签再尝试解析
          const cleanContent = content.replace(/<p>|<\/p>/g, "");
          if (
            cleanContent &&
            (cleanContent.startsWith("{") || cleanContent.startsWith("["))
          ) {
            const parsedContent = JSON.parse(cleanContent);
            if (parsedContent && parsedContent.content) {
              content = parsedContent.content;
            }
          }
        }
      } catch (e) {
        // 如果解析失败，保持原样
        console.log("消息内容不是JSON格式或解析失败", e);
      }

      // 检查是否是图片URL
      if (isImageUrl(content)) {
        content = `<img src="${content}" alt="表情" style="max-width: 100%; border-radius: 8rpx;">`;
      } else if (!content.startsWith("<")) {
        // 如果内容不是HTML标签开头，则包装为<p>标签
        content = `<p>${content}</p>`;
      }
    }

    const newMessage = {
      oId: message.oId || Date.now().toString(),
      content: content,
      time: message.time || formatDate(new Date(), "YYYY-MM-DD HH:mm:ss"),
      fromId: message.fromId,
      senderUserName: message.senderUserName,
      senderAvatar: message.senderAvatar || "",
      receiverUserName: message.receiverUserName || theOtherSideUserName.value,
      preview:
        typeof content === "string" ? content.replace(/<[^>]*>/g, "") : content,
    };

    messages.value.push(newMessage);
    nextTick(() => {
      scrollToBottom(0);
    });
  } catch (error) {
    console.error("处理消息失败:", error, message);
  }
};

// 发送消息
const sendMessage = async () => {
  if (!messageContent.value.trim() || sending.value || !isConnected.value)
    return;

  try {
    sending.value = true;

    // 获取消息内容
    const content = messageContent.value;
    let formattedContent = "";

    // 检测内容是否为URL图片
    const isImageUrl =
      content.match(/\.(jpeg|jpg|gif|png)$/i) ||
      content.match(/^https?:\/\/[^\s]+\.(jpeg|jpg|gif|png)(\?[^\s]*)?$/i);

    if (isImageUrl) {
      formattedContent = `<img src="${content}" alt="图片" />`;
    } else {
      formattedContent = `<p>${content}</p>`;
    }

    // 获取当前时间，使用完整的时间格式
    const currentTime = formatDate(new Date(), "YYYY-MM-DD HH:mm:ss");

    // 添加临时消息到列表
    const tempMessage = {
      oId: Date.now().toString(),
      content: formattedContent,
      time: currentTime,
      fromId: currentUser.value.oId,
      senderUserName: currentUser.value.userName,
      senderAvatar: currentUser.value.userAvatarURL,
      receiverUserName: chatTarget.value.userName,
      preview: content,
    };

    messages.value.push(tempMessage);
    messageContent.value = "";

    // 滚动到底部
    nextTick(() => {
      scrollToBottom(0);
    });

    // 发送 WebSocket 消息
    if (socketTask.value && isConnected.value) {
      socketTask.value.send({
        data: content, // 直接发送内容，不需要包装成JSON
        fail: (err) => {
          console.error("发送消息失败:", err);
          showError("发送失败，请重试");
          // 移除临时消息
          messages.value = messages.value.filter(
            (msg) => msg.oId !== tempMessage.oId
          );
        },
      });
    } else {
      showError("连接已断开，请重试");
      // 移除临时消息
      messages.value = messages.value.filter(
        (msg) => msg.oId !== tempMessage.oId
      );
    }
  } catch (error) {
    showError(error.message || "发送失败");
  } finally {
    sending.value = false;
  }
};

// 处理输入框回车事件
const handleInputConfirm = () => {
  if (messageContent.value.trim()) {
    sendMessage();
  }
};

// 优化的滚动到底部函数
const scrollToBottom = (delay = 100) => {
  setTimeout(() => {
    try {
      // 创建选择器查询
      const query = uni.createSelectorQuery().in(this);
      query.select("#chat-scroll").boundingClientRect();
      query.select(".chat-list").boundingClientRect();

      query.exec((res) => {
        if (res && res[0] && res[1]) {
          const scrollHeight = res[1].height;
          const viewHeight = res[0].height;

          // 计算需要滚动的位置，添加一点额外空间确保完全滚动到底部
          const newScrollTop = scrollHeight - viewHeight + 100;

          if (newScrollTop > 0) {
            // 直接设置滚动位置，不使用动画
            scrollTop.value = newScrollTop;

            // 延迟后再次检查并滚动，确保完全滚动到底部
            setTimeout(() => {
              query.exec((res) => {
                if (res && res[0] && res[1]) {
                  const finalScrollHeight = res[1].height;
                  const finalViewHeight = res[0].height;
                  const finalScrollTop =
                    finalScrollHeight - finalViewHeight + 100;

                  // 如果最终滚动位置大于当前滚动位置，则再次滚动
                  if (finalScrollTop > scrollTop.value) {
                    scrollTop.value = finalScrollTop;
                  }
                }
              });
            }, 100);
          }
        } else {
          // 备用方案：设置一个很大的值
          scrollTop.value = 999999;
        }
      });
    } catch (error) {
      console.error("滚动到底部失败:", error);
      // 备用方案
      scrollTop.value = 999999;
    }
  }, delay);
};

// 处理输入框聚焦事件
const handleInputFocus = () => {
  commentFocus.value = true;
  showEmojiPanel.value = false;
  showMorePanel.value = false;
  // 输入框获取焦点时，延迟滚动到底部，确保键盘弹出后再滚动
  setTimeout(() => {
    scrollToBottom(300);
  }, 300);
};

// 处理输入框失焦事件
const handleInputBlur = () => {
  commentFocus.value = false;
  keyboardHeight.value = 0;
};

// 监听键盘高度变化
// #ifdef APP-PLUS
uni.onKeyboardHeightChange((res) => {
  if (res.height === 0) {
    // 键盘收起时，重置键盘高度和焦点状态
    keyboardHeight.value = 0;
    commentFocus.value = false;
  } else {
    keyboardHeight.value = res.height;
  }
});
// #endif

// 计算内容区域高度
const calculateContentHeight = () => {
  const systemInfo = uni.getSystemInfoSync();
  const windowHeight = systemInfo.windowHeight;
  const headerHeight = 90; // rpx
  const inputHeight = 90; // rpx

  // 转换rpx为px
  const headerHeightPx = uni.upx2px(headerHeight);
  const inputHeightPx = uni.upx2px(inputHeight);

  contentHeight.value = windowHeight - headerHeightPx - inputHeightPx;
};

// 格式化日期标题
const formatDateHeader = (timeStr) => {
  if (!timeStr) return "";

  try {
    const messageDate = new Date(timeStr);
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);

    if (
      messageDate.getDate() === today.getDate() &&
      messageDate.getMonth() === today.getMonth() &&
      messageDate.getFullYear() === today.getFullYear()
    ) {
      return "今天";
    } else if (
      messageDate.getDate() === yesterday.getDate() &&
      messageDate.getMonth() === yesterday.getMonth() &&
      messageDate.getFullYear() === yesterday.getFullYear()
    ) {
      return "昨天";
    } else {
      const year = messageDate.getFullYear();
      const month = messageDate.getMonth() + 1;
      const day = messageDate.getDate();
      return `${year}年${String(month).padStart(2, "0")}月${String(
        day
      ).padStart(2, "0")}日`;
    }
  } catch (error) {
    console.error("格式化日期失败:", error);
    return timeStr;
  }
};

// 格式化消息时间
const formatMessageTime = (timeStr) => {
  if (!timeStr) return "";
  return timeStr.slice(11, 16); // 返回HH:mm
};

// 判断两个日期是否是不同的天
const isDifferentDay = (time1, time2) => {
  if (!time1 || !time2) return false;

  const date1 = new Date(time1);
  const date2 = new Date(time2);

  return (
    date1.getDate() !== date2.getDate() ||
    date1.getMonth() !== date2.getMonth() ||
    date1.getFullYear() !== date2.getFullYear()
  );
};

// 判断是否应该显示时间分隔
const shouldShowTime = (index, message) => {
  if (index === 0) return true;

  const prevMessage = messages.value[index - 1];
  if (!prevMessage || !prevMessage.time || !message.time) return true;

  const prevTime = new Date(prevMessage.time);
  const currentTime = new Date(message.time);

  // 如果时间间隔超过5分钟，显示时间
  return currentTime - prevTime > 5 * 60 * 1000;
};

// 判断是否为自己发送的消息
const isSelfSender = (message) => {
  if (!currentUser.value) return false;
  return message.fromId === currentUser.value.oId;
};

// 格式化内容（处理链接和图片等）
const formatContent = (content) => {
  if (!content) return "";

  try {
    // 创建一个临时的DOM元素来解析HTML
    // 注意：由于uni-app环境限制，我们使用正则表达式进行处理

    // 针对复杂的img标签问题，先尝试修复明显的错误
    let safeContent = content
      // 修复被截断的URL查询参数
      .replace(/(<img[^>]*src=["'][^"']*)(["'][^>]*>)(\?[^<]*)/g, "$1$3$2")
      // 修复常见的HTML实体
      .replace(/&lt;/g, "<")
      .replace(/&gt;/g, ">")
      .replace(/&amp;/g, "&")
      .replace(/&quot;/g, '"');

    // 为所有图片添加点击事件属性和样式
    safeContent = safeContent.replace(/<img([^>]*)>/g, (match, attributes) => {
      // 提取图片URL
      const srcMatch = attributes.match(/src=["']([^"']*)["']/);
      if (!srcMatch) return match;

      const imgUrl = srcMatch[1];
      const dataAttr = `data-url="${imgUrl}" data-type="image"`;

      // 如果已经有class属性，添加chat-image类
      if (attributes.includes("class=")) {
        return match.replace(
          /class=["']([^"']*)["']/g,
          `class="$1 chat-image" ${dataAttr}`
        );
      } else {
        // 如果没有class属性，添加一个
        return `<img${attributes} class="chat-image" ${dataAttr}>`;
      }
    });

    // 将明显的图片URL转换为图片标签
    safeContent = safeContent.replace(
      /(?<!["'=])(https?:\/\/[^\s<]+\.(jpg|jpeg|png|gif|webp)(\?[^\s<]*)?)/gi,
      '<img src="$1" class="chat-image" data-url="$1" data-type="image" style="max-width: 100%; border-radius: 8rpx;">'
    );

    // 处理纯文本URL（排除已经处理过的图片URL）
    safeContent = safeContent.replace(
      /(?<!(href="|src="|<img[^>]*|<a[^>]*))(https?:\/\/[^\s<]+)(?!(["']|[^<]*>))/g,
      '<a href="$2" style="color: #0072ff; text-decoration: underline;">$2</a>'
    );

    return safeContent;
  } catch (error) {
    console.error("格式化内容时出错：", error);
    // 出错时返回原始内容，确保显示不会完全失败
    return content;
  }
};

// 处理消息点击事件
const handleMessageTap = (event, message) => {
  // 获取点击的元素
  const target = event.target;
  console.log("点击的元素:", target);

  // 尝试直接从消息内容中检测图片
  const imageUrl = findChatImage(message.content);
  if (imageUrl) {
    console.log("从消息内容中检测到图片:", imageUrl);
    openImagePreview(imageUrl);
    return;
  }

  // 如果消息内容没有直接检测到图片，尝试从点击对象获取
  if (target && target.dataset && target.dataset.type === "image") {
    const clickedImageUrl = target.dataset.url;
    if (clickedImageUrl) {
      console.log("从点击对象获取到图片:", clickedImageUrl);
      openImagePreview(clickedImageUrl);
      return;
    }
  }

  // 尝试从事件对象查找图片元素
  if (event.currentTarget) {
    try {
      const imageElements =
        event.currentTarget.getElementsByClassName("chat-image");
      if (imageElements && imageElements.length > 0) {
        const firstImage = imageElements[0];
        const firstImageUrl =
          firstImage.getAttribute("src") || firstImage.dataset.url;
        if (firstImageUrl) {
          console.log("从DOM元素中找到图片:", firstImageUrl);
          openImagePreview(firstImageUrl);
          return;
        }
      }
    } catch (error) {
      console.error("查找图片元素出错:", error);
    }
  }

  console.log("未能检测到图片，消息内容:", message.content);
};

// 图片预览相关变量
const previewImageUrl = ref("");
const showImagePreview = ref(false);

// 打开图片预览
const openImagePreview = (url) => {
  previewImageUrl.value = url;
  showImagePreview.value = true;
};

// 关闭图片预览
const closeImagePreview = () => {
  showImagePreview.value = false;
};

// 切换到默认表情页
const switchToDefaultTab = () => {
  activeEmojiTab.value = "default";
  selectedEmojiIndex.value = -1; // 重置删除状态
  if (defaultEmoticons.value.length === 0 && !isLoadingEmoticons.value) {
    loadDefaultEmoticons();
  }
};

// 切换到自定义表情页
const switchToCustomTab = () => {
  activeEmojiTab.value = "custom";
  selectedEmojiIndex.value = -1; // 重置删除状态
  if (!hasLoadedCustomEmoticons.value && !isLoadingCustomEmoticons.value) {
    loadCustomEmoticons();
  }
};

// 加载默认表情
const loadDefaultEmoticons = async () => {
  if (isLoadingEmoticons.value) return;

  try {
    isLoadingEmoticons.value = true;
    // 加载默认表情
    const defaultRes = await api.chat.getDefaultEmoticon();
    if (defaultRes.code === 0) {
      // 处理特殊格式的默认表情包
      if (Array.isArray(defaultRes.data)) {
        // 检查是否是每个元素都是一个对象，且对象只有一个键值对的格式
        const firstItem = defaultRes.data[0];
        if (
          firstItem &&
          typeof firstItem === "object" &&
          Object.keys(firstItem).length === 1
        ) {
          // 特殊格式：[{smile: "😄"}, {flushed: "😳"}, ...]
          // 将其转换为表情符号数组
          defaultEmoticons.value = defaultRes.data.map((item) => {
            const key = Object.keys(item)[0];
            return item[key];
          });
        } else {
          // 普通数组格式，直接使用
          defaultEmoticons.value = defaultRes.data;
        }
      } else if (defaultRes.data && typeof defaultRes.data === "object") {
        // 如果是对象格式，尝试提取emotions字段或其他数组字段
        defaultEmoticons.value =
          defaultRes.data.emotions ||
          Object.values(defaultRes.data).find((val) => Array.isArray(val)) ||
          [];
      } else {
        defaultEmoticons.value = [];
      }
    }
  } catch (error) {
    console.error("加载默认表情包失败", error);
    defaultEmoticons.value = [];
  } finally {
    isLoadingEmoticons.value = false;
  }
};

// 加载自定义表情
const loadCustomEmoticons = async () => {
  if (isLoadingCustomEmoticons.value) return;

  try {
    isLoadingCustomEmoticons.value = true;
    // 加载用户表情包
    const customRes = await api.chat.getEmoticon();
    if (customRes.code === 0) {
      if (Array.isArray(customRes.data)) {
        // 检查是否是与默认表情包相同的特殊格式
        const firstItem = customRes.data[0];
        if (
          firstItem &&
          typeof firstItem === "object" &&
          Object.keys(firstItem).length === 1
        ) {
          // 特殊格式，将其转换为表情符号或URL数组
          customEmoticons.value = customRes.data
            .map((item) => {
              const key = Object.keys(item)[0];
              return item[key];
            })
            .reverse(); // 反转顺序，最新的在前面
        } else {
          // 普通数组格式
          customEmoticons.value = [...customRes.data].reverse(); // 反转顺序，最新的在前面
        }
      } else if (
        customRes.data &&
        typeof customRes.data === "string" &&
        customRes.data.trim()
      ) {
        try {
          const parsedData = JSON.parse(customRes.data);
          if (Array.isArray(parsedData)) {
            // 同样检查特殊格式
            const firstItem = parsedData[0];
            if (
              firstItem &&
              typeof firstItem === "object" &&
              Object.keys(firstItem).length === 1
            ) {
              customEmoticons.value = parsedData
                .map((item) => {
                  const key = Object.keys(item)[0];
                  return item[key];
                })
                .reverse(); // 反转顺序，最新的在前面
            } else {
              customEmoticons.value = [...parsedData]; // 已经是反转过的，保持原样
            }
          } else if (parsedData && typeof parsedData === "object") {
            // 尝试从对象中提取数组
            const possibleArray = Object.values(parsedData).find((val) =>
              Array.isArray(val)
            );
            if (possibleArray) {
              customEmoticons.value = [...possibleArray].reverse(); // 反转顺序，最新的在前面
            } else {
              console.log("表情包数据格式不是数组:", parsedData);
              customEmoticons.value = [];
            }
          } else {
            console.log("表情包数据格式不正确:", parsedData);
            customEmoticons.value = [];
          }
        } catch (e) {
          console.error("解析表情包数据失败", e);
          console.log("原始数据:", customRes.data);
          customEmoticons.value = [];
        }
      } else {
        console.log("表情包数据为空或非法格式");
        customEmoticons.value = [];
      }
    } else {
      console.log("获取表情包失败:", customRes.msg);
      customEmoticons.value = [];
    }
    hasLoadedCustomEmoticons.value = true;
  } catch (error) {
    console.error("加载自定义表情包失败", error);
    customEmoticons.value = [];
  } finally {
    isLoadingCustomEmoticons.value = false;
  }
};

// 添加自定义表情
const addCustomEmoji = () => {
  uni.chooseImage({
    count: 1, // 默认9
    sizeType: ["compressed"], // 可以指定是原图还是压缩图，默认二者都有
    sourceType: ["album", "camera"], // 从相册选择或拍照
    success: async (res) => {
      try {
        showLoading("上传中...");
        const tempFilePath = res.tempFilePaths[0];

        // 上传图片
        const uploadResult = await api.user.uploadImage(tempFilePath);

        if (uploadResult.code === 0) {
          // 获取文件名和上传成功的图片URL
          const fileName = tempFilePath.split("/").pop();
          // 获取上传成功的图片URL
          const imageUrl =
            uploadResult.data.succMap[fileName] ||
            uploadResult.data.fileUrl ||
            uploadResult.data.url;

          if (!imageUrl) {
            throw new Error("未获取到图片URL");
          }

          // 向自定义表情列表添加新表情 - 添加到数组前面，而不是末尾
          const newCustomEmoticons = [imageUrl, ...customEmoticons.value];

          // 同步到服务器
          await api.chat.syncEmoticon(
            "emojis",
            JSON.stringify(newCustomEmoticons)
          );

          // 更新本地表情列表
          customEmoticons.value = newCustomEmoticons;

          showSuccess("添加表情成功");
        } else {
          showError(uploadResult.msg || "上传失败");
        }
      } catch (error) {
        console.error("添加表情失败:", error);
        showError(error.message || "添加表情失败");
      } finally {
        hideLoading();
      }
    },
  });
};

// 选择表情并发送
const selectEmoji = async (emoji) => {
  try {
    sending.value = true;
    // 获取当前时间
    const currentTime = formatDate(new Date(), "YYYY-MM-DD HH:mm:ss");

    // 检查是否是图片URL
    const isImg = isImageUrl(emoji);
    let messageContent = "";

    if (isImg) {
      // 如果是图片URL，使用img标签
      messageContent = `<img src="${emoji}" alt="表情" style="max-width: 100%; border-radius: 8rpx;">`;
    } else {
      // 普通emoji直接包在p标签内
      messageContent = `<p>${emoji}</p>`;
    }

    // 添加临时消息到列表
    const tempMessage = {
      oId: Date.now().toString(),
      content: messageContent,
      time: currentTime,
      fromId: currentUser.value.oId,
      senderUserName: currentUser.value.userName,
      senderAvatar: currentUser.value.userAvatarURL,
      receiverUserName: chatTarget.value.userName,
      preview: isImg ? "[表情]" : emoji,
    };

    messages.value.push(tempMessage);
    showEmojiPanel.value = false;

    // 滚动到底部
    nextTick(() => {
      scrollToBottom(0);
    });

    // 发送 WebSocket 消息
    if (socketTask.value && isConnected.value) {
      socketTask.value.send({
        data: isImg ? messageContent : emoji, // 图片发送HTML标签，表情直接发送
        fail: (err) => {
          console.error("发送消息失败:", err);
          showError("发送失败，请重试");
          // 移除临时消息
          messages.value = messages.value.filter(
            (msg) => msg.oId !== tempMessage.oId
          );
        },
      });
    } else {
      showError("连接已断开，请重试");
      // 移除临时消息
      messages.value = messages.value.filter(
        (msg) => msg.oId !== tempMessage.oId
      );
    }
  } catch (error) {
    showError(error.message || "发送失败");
  } finally {
    sending.value = false;
  }
};

// 切换表情面板
const handleEmoji = () => {
  // 重置删除状态
  selectedEmojiIndex.value = -1;

  if (!showEmojiPanel.value) {
    // 如果打开表情面板，默认加载默认表情
    if (defaultEmoticons.value.length === 0) {
      loadDefaultEmoticons();
    }
  }
  showEmojiPanel.value = !showEmojiPanel.value;
  showMorePanel.value = false;

  // 重置为默认标签页
  if (showEmojiPanel.value) {
    activeEmojiTab.value = "default";
  }
};

// 处理表情选项卡切换
const handleEmojiTabChange = (e) => {
  const current = e.detail.current;
  activeEmojiTab.value = current === 0 ? "default" : "custom";

  // 如果切换到自定义表情标签且未加载过
  if (
    current === 1 &&
    !hasLoadedCustomEmoticons.value &&
    !isLoadingCustomEmoticons.value
  ) {
    loadCustomEmoticons();
  }
};

// 返回上一页
const goBack = () => {
  uni.navigateBack({
    delta: 1,
  });
};

// 跳转到登录页
const goToLogin = () => {
  uni.navigateTo({
    url: "/pages/login/login",
  });
};

// 切换功能面板
const toggleMorePanel = () => {
  showMorePanel.value = !showMorePanel.value;
  if (showMorePanel.value) {
    showEmojiPanel.value = false;
  }
};

// 处理转账
const handleTransfer = () => {
  showMorePanel.value = false;
  showTransferModal.value = true;
  transferAmount.value = "";
  transferMemo.value = "私信转账";
};

// 关闭转账弹框
const closeTransferModal = () => {
  showTransferModal.value = false;
};

// 确认转账
const confirmTransfer = () => {
  const amount = parseFloat(transferAmount.value);
  if (isNaN(amount) || amount <= 0) {
    showError("请输入有效的金额");
    return;
  }

  // 二次确认
  uni.showModal({
    title: "确认转账",
    content: `确定向 ${theOtherSideUserName.value} 转账 ${amount} 积分${
      transferMemo.value ? `（${transferMemo.value}）` : ""
    }吗？`,
    success: async (confirmRes) => {
      if (confirmRes.confirm) {
        try {
          showLoading("转账中...");
          const result = await api.user.transfer(
            theOtherSideUserName.value,
            amount,
            transferMemo.value
          );
          hideLoading();
          if (result.code === 0) {
            showSuccess("转账成功");
            // 发送一条转账消息
            const currentTime = formatDate(new Date(), "YYYY-MM-DD HH:mm:ss");
            const transferMessage = {
              content: `转账 ${amount} 积分${
                transferMemo.value ? `（${transferMemo.value}）` : ""
              }`,
              time: currentTime,
              fromId: currentUser.value.oId,
              senderUserName: currentUser.value.userName,
              senderAvatar: currentUser.value.userAvatarURL,
              receiverUserName: theOtherSideUserName.value,
              preview: `转账 ${amount} 积分${
                transferMemo.value ? `（${transferMemo.value}）` : ""
              }`,
            };

            // 添加临时消息到列表
            messages.value.push(transferMessage);
            nextTick(() => {
              scrollToBottom(0);
            });

            // 发送 WebSocket 消息
            if (socketTask.value && isConnected.value) {
              socketTask.value.send({
                data: `转账 ${amount} 积分${
                  transferMemo.value ? `（${transferMemo.value}）` : ""
                }`,
                fail: (err) => {
                  console.error("发送消息失败:", err);
                  showError("发送失败，请重试");
                  // 移除临时消息
                  messages.value = messages.value.filter(
                    (msg) => msg.oId !== transferMessage.oId
                  );
                },
              });
            } else {
              showError("连接已断开，请重试");
              // 移除临时消息
              messages.value = messages.value.filter(
                (msg) => msg.oId !== transferMessage.oId
              );
            }

            closeTransferModal();
          } else {
            showError(result.msg || "转账失败");
          }
        } catch (error) {
          hideLoading();
          if (error.message === "未登录") {
            uni.navigateTo({
              url: "/pages/login/login",
            });
          } else {
            showError(error.message || "转账失败");
          }
        }
      }
    },
  });
};

// 窗口大小变化回调函数
const handleWindowResize = (res) => {
  calculateContentHeight();
};

// 处理图片上传
const handleUploadImage = () => {
  showMorePanel.value = false;
  // 选择图片
  chooseAndUploadImage({
    count: 9,
    loadingText: "上传中...",
    showSuccessTip: false,
  })
    .then(async (imageUrls) => {
      if (Array.isArray(imageUrls)) {
        for (let i = 0; i < imageUrls.length; i++) {
          await sendImageMessage(imageUrls[i]);
        }
        showSuccess("发送成功");
      } else {
        await sendImageMessage(imageUrls);
        showSuccess("发送成功");
      }
    })
    .catch((error) => {
      console.error("上传图片失败:", error);
    });
};

// 发送单张图片消息
const sendImageMessage = async (imageUrl) => {
  return new Promise((resolve, reject) => {
    try {
      const currentTime = formatDate(new Date(), "YYYY-MM-DD HH:mm:ss");
      const imageMessage = {
        oId: Date.now().toString(),
        content: `<img src="${imageUrl}" alt="图片" style="max-width: 100%; border-radius: 8rpx;">`,
        time: currentTime,
        fromId: currentUser.value.oId,
        senderUserName: currentUser.value.userName,
        senderAvatar: currentUser.value.userAvatarURL,
        receiverUserName: chatTarget.value.userName,
        preview: "图片",
      };

      // 添加临时消息到列表
      messages.value.push(imageMessage);

      // 滚动到底部
      nextTick(() => {
        scrollToBottom(0);
      });

      // 发送 WebSocket 消息
      if (socketTask.value && isConnected.value) {
        socketTask.value.send({
          data: `<img src="${imageUrl}" alt="图片" style="max-width: 100%; border-radius: 8rpx;">`,
          success: () => {
            resolve();
          },
          fail: (err) => {
            console.error("发送消息失败:", err);
            // 移除临时消息
            messages.value = messages.value.filter(
              (msg) => msg.oId !== imageMessage.oId
            );
            reject(new Error("发送失败"));
          },
        });
      } else {
        // 移除临时消息
        messages.value = messages.value.filter(
          (msg) => msg.oId !== imageMessage.oId
        );
        reject(new Error("连接已断开"));
      }
    } catch (error) {
      reject(error);
    }
  });
};

// 处理 WebSocket 错误
const handleWebSocketError = (err) => {
  isConnected.value = false;
  // 只有在页面可见时才尝试重连
  if (isPageVisible.value) {
    attemptReconnect();
  }
};

// 处理 WebSocket 关闭
const handleWebSocketClose = () => {
  isConnected.value = false;
  // 只有在页面可见时才尝试重连
  if (isPageVisible.value) {
    attemptReconnect();
  } else {
    console.log("页面不可见，不进行重连");
  }
};

// 尝试重连
const attemptReconnect = () => {
  // 如果页面不可见，不进行重连
  if (!isPageVisible.value) {
    console.log("页面不可见，不进行重连");
    return;
  }

  if (reconnectCount.value >= MAX_RECONNECT_COUNT) {
    console.log("达到最大重连次数，停止重连");
    return;
  }

  if (reconnectTimer.value) {
    clearTimeout(reconnectTimer.value);
  }

  reconnectCount.value++;
  const delay = Math.min(1000 * Math.pow(2, reconnectCount.value), 30000); // 指数退避，最大30秒

  reconnectTimer.value = setTimeout(() => {
    console.log(`尝试第 ${reconnectCount.value} 次重连...`);
    connectWebSocket();
  }, delay);
};

// 组件挂载时设置定时检查页面状态
let pageStateCheckInterval = null;
let wasChatPageActive = true; // 跟踪聊天页面的上一个状态

onMounted(() => {
  // 检查并销毁任何可能存在的聊天室WebSocket连接
  const chatRoomWebSocket = useChatWebSocket();
  if (chatRoomWebSocket && typeof chatRoomWebSocket.offAll === "function") {
    console.log("进入私聊页面，取消所有聊天室WebSocket事件注册");
    chatRoomWebSocket.offAll();
  }

  if (
    chatRoomWebSocket &&
    typeof chatRoomWebSocket.destroyCompletely === "function"
  ) {
    console.log("进入私聊页面，强制销毁聊天室WebSocket连接");
    chatRoomWebSocket.destroyCompletely();
  }

  getRouteParams();
  loadUserProfile();
  loadUserInfo();
  calculateContentHeight();
  loadMessages(true);

  // 确保在用户信息加载完成后再建立 WebSocket 连接
  if (isLoggedIn()) {
    connectWebSocket();
  }

  // 使用 uni-app 的 onWindowResize 方法监听窗口大小变化
  try {
    windowResizeListener.value = handleWindowResize; // 保存监听器引用
    uni.onWindowResize(windowResizeListener.value);
  } catch (error) {
    console.error("添加窗口大小变化监听器失败:", error);
  }

  // 定时检查页面状态
  pageStateCheckInterval = setInterval(() => {
    const pages = getCurrentPages();
    const currentPage = pages[pages.length - 1];
    const isChatPageActive =
      currentPage && currentPage.route === "pages/chat/chat-detail";

    // 如果当前页面不是聊天页面，关闭连接
    if (!isChatPageActive) {
      if (wasChatPageActive) {
        console.log("已离开聊天页面，关闭WebSocket连接");
        isPageVisible.value = false;
        closeWebSocketConnection();
        wasChatPageActive = false;
      }
    } else if (!wasChatPageActive) {
      // 如果之前不是聊天页面，现在是，说明是返回了聊天页面
      console.log("返回聊天页面，重新连接WebSocket");
      isPageVisible.value = true;
      if (!isConnected.value && reconnectCount.value < MAX_RECONNECT_COUNT) {
        connectWebSocket();
      }
      wasChatPageActive = true;
    }
  }, 1000); // 每1秒检查一次，响应更快
});

onBeforeUnmount(() => {
  console.log("组件即将卸载，关闭连接");
  isPageVisible.value = false;
  if (pageStateCheckInterval) {
    clearInterval(pageStateCheckInterval);
    pageStateCheckInterval = null;
  }
});

onUnmounted(() => {
  console.log("组件卸载，确保关闭连接");

  // 确保安全地移除所有事件监听
  try {
    // #ifdef APP-PLUS
    uni.offKeyboardHeightChange();
    // #endif
  } catch (error) {
    console.error("移除键盘高度监听失败:", error);
  }

  // 移除窗口大小变化监听
  try {
    if (windowResizeListener.value) {
      // 使用保存的监听器引用
      uni.offWindowResize(windowResizeListener.value);
      windowResizeListener.value = null;
    }
  } catch (error) {
    console.error("移除窗口监听失败:", error);
  }

  // 清除检查间隔
  try {
    if (pageStateCheckInterval) {
      clearInterval(pageStateCheckInterval);
      pageStateCheckInterval = null;
    }
  } catch (error) {
    console.error("清除检查间隔失败:", error);
  }

  // 关闭WebSocket连接
  try {
    closeWebSocketConnection();
  } catch (error) {
    console.error("关闭WebSocket连接失败:", error);
  }

  // 重置重连计数
  reconnectCount.value = 0;
  isConnected.value = false;
});

// 关闭WebSocket连接的函数
const closeWebSocketConnection = () => {
  console.log("执行关闭WebSocket连接函数");
  // 关闭 WebSocket 连接
  if (socketTask.value) {
    try {
      socketTask.value.close({
        success: () => {
          console.log("关闭 WebSocket 连接成功");
        },
        fail: (err) => {
          console.error("关闭 WebSocket 连接失败:", err);
        },
        complete: () => {
          socketTask.value = null;
        },
      });
    } catch (error) {
      console.error("关闭 WebSocket 连接出错:", error);
      socketTask.value = null;
    }
  }
  // 清除重连定时器
  if (reconnectTimer.value) {
    clearTimeout(reconnectTimer.value);
    reconnectTimer.value = null;
  }
};

// 判断是否为图片URL
const isImageUrl = (text) => {
  if (!text || typeof text !== "string") return false;
  return (
    text.startsWith("http") &&
    (text.endsWith(".png") ||
      text.endsWith(".jpg") ||
      text.endsWith(".jpeg") ||
      text.endsWith(".gif") ||
      text.endsWith(".webp") ||
      text.includes(".png?") ||
      text.includes(".jpg?") ||
      text.includes(".jpeg?") ||
      text.includes(".gif?") ||
      text.includes(".webp?"))
  );
};

// 长按表情触发删除模式
const handleLongPress = (index) => {
  // 只允许删除自定义表情
  if (activeEmojiTab.value === "custom") {
    selectedEmojiIndex.value = index;
  }
};

// 删除表情
const deleteEmoji = async (index) => {
  try {
    uni.showModal({
      title: "删除表情",
      content: "确定要删除这个表情吗？",
      success: async (res) => {
        if (res.confirm) {
          showLoading("删除中...");

          // 复制一份表情数组并移除选中项
          const newCustomEmoticons = [...customEmoticons.value];
          newCustomEmoticons.splice(index, 1);

          // 同步到服务器
          await api.chat.syncEmoticon(
            "emojis",
            JSON.stringify(newCustomEmoticons)
          );

          // 更新本地表情列表
          customEmoticons.value = newCustomEmoticons;

          // 重置选中状态
          selectedEmojiIndex.value = -1;

          showSuccess("删除成功");
        } else {
          // 取消删除
          selectedEmojiIndex.value = -1;
        }
      },
    });
  } catch (error) {
    console.error("删除表情失败:", error);
    showError(error.message || "删除失败");
    selectedEmojiIndex.value = -1;
  } finally {
    hideLoading();
  }
};

// 查找并检测聊天图片
const findChatImage = (content) => {
  // 检查是否包含图片
  const hasImage = /<img.*?src=["'](.*?)["'].*?>/i.test(content);
  if (!hasImage) return null;

  // 提取图片URL
  const match = content.match(/<img.*?src=["'](.*?)["'].*?>/i);
  if (match && match[1]) {
    return match[1];
  }
  return null;
};
</script>

<style>
.chat-detail-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #f5f6f7;
}

.chat-header {
  display: flex;
  height: 90rpx;
  background-color: #fff;
  border-bottom: 1rpx solid #f0f0f0;
  position: relative;
  align-items: center;
  padding: 0 30rpx;
  padding-top: 60rpx;
}

.back-btn {
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 99;
}

.header-right-space {
  width: 60rpx;
  height: 60rpx;
}

.user-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
  z-index: 1;
}

.username {
  font-size: 32rpx;
  font-weight: 500;
  color: #333;
  text-align: center;
  width: 100%;
}

.status {
  font-size: 24rpx;
  color: #4caf50;
  margin-top: 4rpx;
}
.status-offline {
  font-size: 24rpx;
  color: #999;
  margin-top: 4rpx;
}
.chat-messages {
  flex: 1;
  overflow: hidden;
  -webkit-overflow-scrolling: touch; /* 增强iOS滚动体验 */
}

.chat-list {
  padding: 20rpx 30rpx;
  display: flex;
  flex-direction: column;
  padding-bottom: 120rpx;
}

.loading-more {
  text-align: center;
  padding: 20rpx 0;
  color: #999;
  font-size: 26rpx;
}

.date-divider {
  text-align: center;
  margin: 20rpx 0;
}

.date-divider text {
  display: inline-block;
  padding: 8rpx 24rpx;
  background-color: rgba(0, 0, 0, 0.05);
  border-radius: 24rpx;
  font-size: 24rpx;
  color: #999;
}

.message-group {
  margin-bottom: 24rpx;
}

.time-indicator {
  text-align: center;
  margin: 16rpx 0;
}

.time-indicator text {
  font-size: 24rpx;
  color: #999;
  background-color: rgba(0, 0, 0, 0.05);
  padding: 4rpx 16rpx;
  border-radius: 12rpx;
}

.message-wrapper {
  display: flex;
  margin-bottom: 4rpx;
}

.self-wrapper {
  flex-direction: row-reverse;
}

.avatar-container {
  margin-right: 16rpx;
}

.self-wrapper .avatar-container {
  margin-right: 0;
  margin-left: 16rpx;
}

.avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background-color: #eee;
  border: 1rpx solid #f0f0f0;
}

.message-content {
  display: flex;
  flex-direction: column;
  max-width: 70%;
  position: relative;
}

.self-content {
  align-items: flex-end;
}

.message-bubble {
  padding: 16rpx 24rpx;
  border-radius: 18rpx;
  margin-bottom: 4rpx;
  word-break: break-all;
  font-size: 30rpx;
  line-height: 1.5;
  position: relative;
}

.other-bubble {
  background-color: #fff;
  color: #333;
  border-top-left-radius: 4rpx;
  box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
}

.self-bubble {
  background-color: #0072ff;
  color: #fff;
  border-top-right-radius: 4rpx;
}

.self-bubble a {
  color: #ffffff !important;
}

.image-container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.chat-image {
  max-width: 100%;
  border-radius: 8rpx;
  cursor: pointer;
  display: block;
  margin: 2rpx 0;
  z-index: 100; /* 提高图片的层级 */
}

.view-image-link {
  text-decoration: underline;
  cursor: pointer;
  font-size: 24rpx;
  color: #999;
  display: inline-block;
  margin-top: 8rpx;
}

.self-bubble .view-image-link {
  color: rgba(255, 255, 255, 0.8);
}

.device-info-container {
  display: inline-block;
  margin-top: 4rpx;
  align-self: flex-end;
}

.other-device-info {
  color: #999;
  font-size: 20rpx;
  background-color: rgba(0, 0, 0, 0.05);
  padding: 2rpx 8rpx;
  border-radius: 8rpx;
}

.self-device-info {
  color: rgba(255, 255, 255, 0.7);
  font-size: 20rpx;
  background-color: rgba(0, 114, 255, 0.2);
  padding: 2rpx 8rpx;
  border-radius: 8rpx;
}

.no-more {
  text-align: center;
  padding: 30rpx 0;
  color: #999;
  font-size: 26rpx;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 100rpx 0;
  flex-grow: 1;
}

.empty-text {
  color: #999;
  font-size: 28rpx;
  margin-top: 20rpx;
}

.input-area {
  position: fixed;
  left: 0;
  right: 0;
  background-color: #fff;
  border-top: 1rpx solid #f0f0f0;
  z-index: 100;
}

.input-wrapper {
  display: flex;
  align-items: center;
  padding: 20rpx;
  height: 90rpx;
}

.emoji-btn {
  width: 70rpx;
  height: 70rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.message-input {
  flex: 1;
  height: 70rpx;
  background-color: #f5f5f5;
  border-radius: 36rpx;
  padding: 0 24rpx;
  margin: 0 16rpx;
  font-size: 28rpx;
}

.more-btn {
  width: 70rpx;
  height: 70rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.send-btn {
  width: 70rpx;
  height: 70rpx;
  border-radius: 35rpx;
  background-color: #0072ff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.emoji-panel {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 400rpx;
  background-color: #fff;
  border-top: 1rpx solid #f0f0f0;
  z-index: 99;
  display: flex;
  flex-direction: column;
}

.emoji-tabs {
  display: flex;
  justify-content: space-around;
  padding: 10rpx 0;
  border-bottom: 1rpx solid #f0f0f0;
  background-color: #f8f8f8;
}

.emoji-tab {
  padding: 10rpx 30rpx;
  cursor: pointer;
  font-size: 28rpx;
  color: #666;
  position: relative;
  transition: all 0.3s;
}

.active-tab {
  color: #0072ff;
  font-weight: 500;
}

.active-tab::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 60rpx;
  height: 4rpx;
  background-color: #0072ff;
  border-radius: 4rpx;
}

.emoji-swiper {
  flex: 1;
  height: 340rpx;
}

.emoji-swiper :deep(.uni-swiper-wrapper) {
  height: 100%;
}

.emoji-swiper :deep(.uni-swiper-item) {
  height: 100%;
  overflow: hidden;
}

.emoji-scroll {
  height: 100%;
  padding: 10rpx;
}

.emoji-list {
  display: flex;
  flex-wrap: wrap;
  padding: 10rpx;
}

.emoji-item {
  width: 16.666%;
  padding: 10rpx;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.emoji-image {
  width: 80rpx;
  height: 80rpx;
  object-fit: contain;
}

.emoji-text {
  font-size: 40rpx;
  line-height: 80rpx;
  text-align: center;
}

.emoji-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.8);
  color: #999;
  font-size: 28rpx;
}

.emoji-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
  color: #999;
  font-size: 28rpx;
  height: 100%;
}

.custom-empty {
  padding-top: 100rpx;
}

.add-emoji-btn {
  margin-top: 30rpx;
  background-color: #0072ff;
  color: #fff;
  font-size: 26rpx;
  padding: 12rpx 30rpx;
  border-radius: 30rpx;
  border: none;
}

.more-panel {
  height: 200rpx;
  background-color: #fff;
  border-top: 1rpx solid #f0f0f0;
  position: absolute;
  bottom: 90rpx;
  left: 0;
  right: 0;
  z-index: 100;
}

.more-list {
  display: flex;
  flex-wrap: wrap;
  padding: 20rpx;
}

.more-item {
  width: 25%;
  height: 120rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.more-item text {
  font-size: 24rpx;
  color: #666;
  margin-top: 8rpx;
}

/* 转账弹框样式 */
.transfer-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.modal-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9998;
}

.modal-content {
  width: 100%;
  background-color: #fff;
  border-radius: 24rpx 24rpx 0 0;
  overflow: hidden;
  z-index: 9999;
  position: relative;
  transition: bottom 0.3s ease;
}

.modal-header {
  padding: 40rpx 30rpx;
  border-bottom: 1rpx solid #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.modal-title {
  font-size: 32rpx;
  font-weight: 500;
  color: #333;
}

.modal-close {
  width: 40rpx;
  height: 40rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-body {
  padding: 40rpx 30rpx;
  padding-bottom: 60rpx;
}

.input-group {
  margin-bottom: 30rpx;
}

.input-label {
  font-size: 28rpx;
  color: #666;
  margin-bottom: 16rpx;
  display: block;
}

.input-wrapper {
  display: flex;
  align-items: center;
  height: 100rpx;
  background-color: #f5f5f5;
  border-radius: 12rpx;
  padding: 0 20rpx;
}

.currency-symbol {
  font-size: 40rpx;
  color: #333;
  margin-right: 10rpx;
}

.input-field {
  flex: 1;
  height: 100rpx;
  font-size: 36rpx;
  color: #333;
}

.balance-info {
  margin-top: 20rpx;
  text-align: center;
  font-size: 24rpx;
  color: #999;
}

.modal-footer {
  padding: 30rpx;
  border-top: 1rpx solid #f0f0f0;
  display: flex;
  justify-content: space-between;
  gap: 20rpx;
  position: sticky;
  bottom: 0;
  background-color: #fff;
}

.modal-btn {
  flex: 1;
  height: 80rpx;
  border-radius: 40rpx;
  font-size: 28rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cancel-btn {
  background-color: #f5f5f5;
  color: #666;
}

.confirm-btn {
  background-color: #0072ff;
  color: #fff;
}

.confirm-btn:disabled {
  background-color: #ccc;
  color: #fff;
}

.add-emoji-item {
  display: flex;
  justify-content: center;
  align-items: center;
}

.add-emoji-icon {
  display: flex;
  justify-content: center;
  align-items: center;
}

.emoji-delete-active {
  opacity: 0.5;
}

.emoji-delete-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  width: 60rpx;
  height: 60rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
  z-index: 10;
}

/* 单张图片预览样式 */
.image-preview-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.image-preview-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999; /* 降低z-index值，使其低于ImageViewer中的控制按钮 */
}

/* 消息中图片样式 */
.chat-image {
  max-width: 100%;
  border-radius: 8rpx;
  cursor: pointer;
  display: block;
  margin: 2rpx 0;
}
</style>
